package cn.csc.module.distribute.service.withdraw;

import cn.csc.framework.common.pojo.PageResult;
import cn.csc.framework.mybatis.core.util.MyBatisUtils;
import cn.csc.framework.security.core.util.SecurityFrameworkUtils;
import cn.csc.module.distribute.controller.admin.withdraw.vo.DistributeWithdrawCreateReqVO;
import cn.csc.module.distribute.controller.admin.withdraw.vo.DistributeWithdrawExportReqVO;
import cn.csc.module.distribute.controller.admin.withdraw.vo.DistributeWithdrawPageReqVO;
import cn.csc.module.distribute.controller.admin.withdraw.vo.DistributeWithdrawUpdateReqVO;
import cn.csc.module.distribute.controller.app.distributor.vo.AppDistributorReqVO;
import cn.csc.module.distribute.controller.app.withdraw.vo.AppDistributeWithdrawPageReqVO;
import cn.csc.module.distribute.controller.app.withdraw.vo.AppDistributeWithdrawReqVO;
import cn.csc.module.distribute.convert.bank.BankInfoConvert;
import cn.csc.module.distribute.convert.withdraw.DistributeWithdrawConvert;
import cn.csc.module.distribute.dal.dataobject.bank.BankInfoDO;
import cn.csc.module.distribute.dal.dataobject.distributor.DistributorDO;
import cn.csc.module.distribute.dal.dataobject.withdraw.DistributeWithdrawDO;
import cn.csc.module.distribute.dal.mysql.bank.BankInfoMapper;
import cn.csc.module.distribute.dal.mysql.distributor.DistributorMapper;
import cn.csc.module.distribute.dal.mysql.withdraw.DistributeWithdrawMapper;
import cn.csc.module.member.api.user.MemberUserApi;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.apache.commons.lang.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.time.LocalDateTime;
import java.util.Collection;
import java.util.List;

import static cn.csc.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.csc.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
import static cn.csc.module.distribute.enums.ErrorCodeConstants.*;

/**
 * 提现记录 Service 实现类
 *
 * @author 云隐
 */
@Service
public class DistributeWithdrawServiceImpl extends ServiceImpl<DistributeWithdrawMapper, DistributeWithdrawDO> implements DistributeWithdrawService {

    @Resource
    private DistributeWithdrawMapper withdrawMapper;
    @Resource
    BankInfoMapper bankInfoMapper;
    @Resource
    DistributorMapper distributorMapper;
    @Resource
    private MemberUserApi memberUserApi;

    @Override
    public BigInteger createWithdraw(DistributeWithdrawCreateReqVO createReqVO) {
        // 插入
        DistributeWithdrawDO withdraw = DistributeWithdrawConvert.INSTANCE.convert(createReqVO);
        withdrawMapper.insert(withdraw);
        // 返回
        return withdraw.getId();
    }

    @Transactional
    @Override
    public BigInteger applyWithdraw(AppDistributeWithdrawReqVO appDistributeWithdrawReqVO) {
        Long userId = getLoginUserId();

        AppDistributorReqVO distributorReqVO = new AppDistributorReqVO();
        distributorReqVO.setUserId(new BigInteger(String.valueOf(userId)));
        distributorReqVO.setStatus(1);
        DistributorDO distributorDO = distributorMapper.getDistributorByUserId(distributorReqVO);
        if (distributorDO == null) {
            throw exception(DISTRIBUTOR_NOT_EXISTS);
        }

        if (appDistributeWithdrawReqVO.getApplyAmount().compareTo(BigDecimal.ZERO) <= 0) {
            throw exception(DISTRIBUTOR_POSITIVE_AMOUNT);
        }

        if (appDistributeWithdrawReqVO.getApplyAmount().compareTo(distributorDO.getCommissionWithdrawable()) > 0) {
            throw exception(DISTRIBUTOR_AMOUNT_INFO);
        }

        appDistributeWithdrawReqVO.setMobile(distributorDO.getMobile());
        appDistributeWithdrawReqVO.setName(distributorDO.getName());
        appDistributeWithdrawReqVO.setUserId(new BigInteger(String.valueOf(userId)));

        DistributeWithdrawDO withdraw = DistributeWithdrawConvert.INSTANCE.convert(appDistributeWithdrawReqVO);
        if (StringUtils.isNotBlank(appDistributeWithdrawReqVO.getAcctNo())) {
            BankInfoDO bankInfoDO = BankInfoConvert.INSTANCE.convert1(appDistributeWithdrawReqVO);
            BankInfoDO queryDO = bankInfoMapper.selectInfo(bankInfoDO);

            if (queryDO == null)
                bankInfoMapper.insert(bankInfoDO);
        }
        withdrawMapper.insert(withdraw);
        distributorMapper.updateWithdrawn(appDistributeWithdrawReqVO.getUserId(), withdraw.getApplyAmount());
        return withdraw.getId();
    }

    @Override
    public void updateWithdraw(DistributeWithdrawUpdateReqVO updateReqVO) {
        // 校验存在
        validateWithdrawExists(updateReqVO.getId());
        // 更新
        DistributeWithdrawDO updateObj = DistributeWithdrawConvert.INSTANCE.convert(updateReqVO);
        withdrawMapper.updateById(updateObj);
    }

    @Transactional
    @Override
    public void applyUpdate(DistributeWithdrawUpdateReqVO updateReqVO) {
        DistributeWithdrawDO distributeWithdrawDO = getWithdraw(updateReqVO.getId());
        if (updateReqVO.getActualAmount().compareTo(distributeWithdrawDO.getApplyAmount()) > 0) {
            throw exception(DISTRIBUTOR_AMOUNT_INFO);
        }
        // 更新
        DistributeWithdrawDO updateObj = DistributeWithdrawConvert.INSTANCE.convert(updateReqVO);
        updateObj.setAuditStatus(5);
        updateObj.setAuditDate(LocalDateTime.now());
        withdrawMapper.updateById(updateObj);
        distributorMapper.increFieldWithdrawn(distributeWithdrawDO.getUserId(), updateReqVO.getActualAmount(), distributeWithdrawDO.getApplyAmount().subtract(updateReqVO.getActualAmount()));
    }

    @Transactional
    @Override
    public void applyAudit(DistributeWithdrawUpdateReqVO updateReqVO) {
        DistributeWithdrawDO withdrawDO = getWithdraw(updateReqVO.getId());
        // 更新
        DistributeWithdrawDO updateObj = new DistributeWithdrawDO();
        updateObj.setAuditStatus(10);
        updateObj.setAuditReason(updateReqVO.getAuditReason());
        updateObj.setId(updateReqVO.getId());
        updateObj.setAuditDate(LocalDateTime.now());
        withdrawMapper.updateById(updateObj);
        distributorMapper.increFieldWithdrawable(withdrawDO.getUserId(), withdrawDO.getApplyAmount());
    }

    @Override
    public void deleteWithdraw(BigInteger id) {
        // 校验存在
        validateWithdrawExists(id);
        // 删除
        withdrawMapper.deleteById(id);
    }

    private void validateWithdrawExists(BigInteger id) {
        if (withdrawMapper.selectById(id) == null) {
            throw exception(WITHDRAW_NOT_EXISTS);
        }
    }

    @Override
    public DistributeWithdrawDO getWithdraw(BigInteger id) {
        return withdrawMapper.selectById(id);
    }

    @Override
    public List<DistributeWithdrawDO> getWithdrawList(Collection<BigInteger> ids) {
        return withdrawMapper.selectBatchIds(ids);
    }

    @Override
    public PageResult<DistributeWithdrawDO> getWithdrawPage(DistributeWithdrawPageReqVO pageReqVO) {
        return withdrawMapper.selectPage(pageReqVO);
    }

    @Override
    public PageResult<DistributeWithdrawDO> getWithdrawCustomizePage(DistributeWithdrawPageReqVO pageReqVO) {
        IPage<DistributeWithdrawDO> mpPage = MyBatisUtils.buildPage(pageReqVO);
        withdrawMapper.selectWithdrawPage(pageReqVO, mpPage);
        long totalPage;
        // 多表关联使用mpPage.getRecords().size()
        if (mpPage.getRecords().size() > 0) {
            if (mpPage.getRecords().size() % pageReqVO.getPageSize() <= 0)
                totalPage = mpPage.getRecords().size() / pageReqVO.getPageSize();
            else
                totalPage = (mpPage.getRecords().size() / pageReqVO.getPageSize()) + 1;
        } else {
            return new PageResult<>();
        }
        return new PageResult<>(mpPage.getRecords(), (long) mpPage.getRecords().size(), totalPage);
    }

    @Override
    public PageResult<DistributeWithdrawDO> getAppWithdrawPage(AppDistributeWithdrawPageReqVO pageReqVO) {
        Long userId = SecurityFrameworkUtils.getLoginUserId();
        pageReqVO.setUserId( BigInteger.valueOf(userId));
        return withdrawMapper.selectAppPage(pageReqVO);
    }

    @Override
    public List<DistributeWithdrawDO> getWithdrawList(DistributeWithdrawExportReqVO exportReqVO) {
        return withdrawMapper.selectList(exportReqVO);
    }


}
